import tornado.ioloop
import tornado.web
import tornado.httpclient
import tornado.httpserver
import json
import time
import datetime
import urllib
import uuid
import os
import zipfile
import ssl
import Foundation, objc
import shutil

NSDictionary = objc.lookUpClass('NSDictionary')
StaticDir =  os.path.join(os.path.dirname(__file__),'../'+'static')
UploadDir = 'static/upload'
UploadPath = os.path.join(StaticDir,'upload')
Base_Url = 'http://127.0.0.1:'
PORT = '8888'
Home_Url =  Base_Url+PORT
Https_Url = 'https:localhost:8888' + UploadDir

class ZFile(object):
    def __init__(self, filename, mode='r', basedir=''):
        self.filename = filename
        self.mode = mode
        if self.mode in ('w', 'a'):
            self.zfile = zipfile.ZipFile(filename, self.mode, compression=zipfile.ZIP_DEFLATED)
        else:
            self.zfile = zipfile.ZipFile(filename, self.mode)
        self.basedir = basedir
        if not self.basedir:
            self.basedir = os.path.dirname(filename)

    def addfile(self, path, arcname=None):
        path = path.replace('//', '/')
        if not arcname:
            if path.startswith(self.basedir):
                arcname = path[len(self.basedir):]
            else:
                arcname = ''
        self.zfile.write(path, arcname)

    def addfiles(self, paths):
        for path in paths:
            if isinstance(path, tuple):
                self.addfile(*path)
            else:
                self.addfile(path)

    def close(self):
        self.zfile.close()

    def extract_to(self, path):
        for p in self.zfile.namelist():
            self.extract(p, path)

    def extract(self, filename, path):
        if not filename.endswith('/'):
            f = os.path.join(path, filename)
            dir = os.path.dirname(f)
            if not os.path.exists(dir):
                os.makedirs(dir)
            with open(f,'wb') as up:
                  up.write(self.zfile.read(filename))
                  up.close()


class BaseHandler(tornado.web.RequestHandler):
    def get(self):
        self.write_error(status_code=404)
    def write_error(self, status_code, **kwargs):
        if status_code == 404:
            self.render('404.html')
        elif status_code == 500:
            self.render('500.html')
        else:
            self.write('error:' + str(status_code))


class MainHandler(BaseHandler):
    def get(self):
        self.render('index.html')

class UploadHanlder(BaseHandler):
    def get(self):
        url = self.request.protocol + '://' + self.request.host + '/upload'
        self.render('upload.html',MURL=url)
        self.write_error()
    def post(self):
        if self.request.files:
             files = self.request.files
             file_metas=self.request.files['file_data']    #提取表单中‘name’为‘file’的文件元数据
             for meta in file_metas:
                 filename=  str(uuid.uuid1())+'.ipa'
                 filepath=os.path.join(UploadPath,filename)
                 with open(filepath,'wb') as up:      #有些文件需要已二进制的形式存储，实际中可以更改
                    up.write(meta['body'])
                    up.close()
                    dir = filepath+'zip'
                    z = ZFile(filepath)
                    z.extract_to(dir)
                    z.close()
                    unzipDir = os.path.join(dir,'Payload')
                    for i in os.listdir(unzipDir):
                        appPath = os.path.join(unzipDir,i)
                        plistPath = os.path.join(appPath,'Info.plist')
                        if os.path.exists(plistPath):
                           dict = NSDictionary.dictionaryWithContentsOfFile_(plistPath)
                           plist = self.render_string('item.plist',IPA_URL=Home_Url+'/'+UploadDir+'/'+filename,Bundle_ID=dict.objectForKey_('CFBundleIdentifier'),
                                               Bundle_VERSION=dict.objectForKey_('CFBundleVersion'),Title=dict.objectForKey_('CFBundleDisplayName'))
                           f = open(os.path.join(UploadPath,filename+'.plist'),'wb')
                           f.write(plist)
                           f.close()
                           shutil.rmtree(dir)
                           plistUrl = self.request.protocol + '://' + self.request.host + '/install' + '?file=' +filename+'.plist'
                           self.write(json.dumps({'url':plistUrl}))
                           break



class installHandler(BaseHandler):
      def get(self):
        fileName = self.get_query_argument('file')
        self.render('install.html',plist=Https_Url+'/'+fileName)




settings={
    'template_path':os.path.join(os.path.dirname(__file__),'../templates'),
    'static_path':os.path.join(os.path.dirname(__file__),'../static'),
    'debug':True,
}

application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/upload.*",UploadHanlder),
    (r"/install.*",installHandler),
    (r".*",BaseHandler),
],**settings)
if __name__ == "__main__":
    data_dir = os.path.join(StaticDir,'ssl')
    application.listen(PORT,max_buffer_size=1024*1024*1024,ssl_options={
"certfile": os.path.join(data_dir, "server.crt"),
"keyfile": os.path.join(data_dir, "server.key"),

})
    application.listen(8000)
    tornado.ioloop.IOLoop.instance().start()